package com.csx.micrometer.invoke.core.inbound.servlet;

import com.csx.micrometer.common.util.MetricsUtil;
import com.csx.micrometer.invoke.constant.InvokeConstant;
import com.csx.micrometer.invoke.constant.InvokeMetricsConstant;
import com.csx.micrometer.invoke.context.servlet.MicrometerHttpServletRequest;
import com.csx.micrometer.invoke.context.servlet.MicrometerHttpServletResponse;
import com.csx.micrometer.invoke.custom.TagsCustom;
import io.micrometer.core.instrument.Tags;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.List;

/**
 * 用于统计servlet请求指标的拦截器
 * @author cuisongxu
 * @date 2022/11/30 18:57
 */
public class MicrometerServletHandlerInboundInterceptor implements HandlerInterceptor {

    private final Logger logger = LoggerFactory.getLogger(MicrometerServletHandlerInboundInterceptor.class);

    /**
     * 标签定制器
     */
    private final List<TagsCustom> tagsCustoms;

    public MicrometerServletHandlerInboundInterceptor(List<TagsCustom> tagsCustoms) {
        this.tagsCustoms = tagsCustoms;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 记录 处理请求 的起始时间
        request.setAttribute(InvokeConstant.REQUEST_PROCESS_START_TIME, System.currentTimeMillis());
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        try {
            long requestProcessStartMillis = Long.parseLong(String.valueOf(request.getAttribute(InvokeConstant.REQUEST_PROCESS_START_TIME)));
            long requestProcessEndMillis = System.currentTimeMillis();

            // 请求处理耗时
            long requestProcessDurationMillis = (requestProcessEndMillis - requestProcessStartMillis);

            // 自定义tags
            Tags tags = Tags.of(Collections.emptyList());
            for (TagsCustom tagsCustom : tagsCustoms) {
                tags = tagsCustom.customTags(new MicrometerHttpServletRequest(request), new MicrometerHttpServletResponse(response), tags);
            }
            logger.info("all tags custom result: " + tags.toString());

            // 统计指标
            MetricsUtil.record(InvokeMetricsConstant.INVOKE_PROCESS_DURATION_MILLIS, requestProcessDurationMillis, tags);
        }catch (Exception e) {
            logger.error(request.getMethod() + "  " + request.getRequestURI() + "invoke failed because: ", e);
        }

    }
}
